/*
 * PropellerC build manager.
 */

/*
 * default library path
 */
var libPath = "workspace/Libraries/";

/*
 * buildcmd and compiler tool.
 */
var buildcmd = "";
var compiler = "propellerc";
//var compiler = "gcc";

var isWindows= /^win/.test(process.platform);

/*
 * required modules
 */
var fs    = require('fs');
var exec  = require('child_process').exec;
var execf = require('child_process').execFile;

/*
 * propellerc arguments
 */
var memmodel = "cmm";
var optimize = "-Os";
var doubles  = "-m32bit-doubles";
var cstandard= "-std=c99";
var options  = "-fno-exceptions";

module.exports = {
  build:
  function(file, callback) {
    buildC(file, callback);
  },
  setCompiler:
  function(comp) {
    compiler = comp;
  },
  setLibrary:
  function(lib) {
    libPath = lib;
  }
};

/*
 * build C program
 */
var error = "";
function buildC (file, callback)
{
  error = "";
  buildcmd = "";
  if (addFlags(file, compiler, callback)) {
    error = buildcmd;
  }
  /*
  if (error == "" && buildcmd) {
    console.log(buildcmd);
    exec(buildcmd, callback);
  }
  */
  return error;
}

/*
 * create flags
 */
function addFlags(file, ctype, callback)
{
  var opts = optimize +' '+ cstandard + ' '+ options +' ';
  var gcc = 'gcc '+ opts;

  if (ctype == "propellerc") {
    gcc = 'propeller-elf-gcc -m'+ memmodel +' '+ doubles +' '+ opts;
  }

  if(file.match(".cpp")) {
    buildcmd += gcc;
  }
  else if(file.match(".c")) {
    buildcmd += gcc;
  }
  else {
    buildcmd = "Unknown file type '"+ file +"'";
    return true;
  }

  addIncludes(file);
  addLibraryPaths(file);
  addMainArgs(file);
  addLibraries(file);

  buildProgram(file, callback);

  return false;
}

function getFolders(lib)
{
  var folders = Array();
  var dirs = fs.readdirSync(lib);
  for (var n in dirs) {
    //console.log('-I "'+lib+dirs[n]+'" ');
    var sdirs = fs.readdirSync(lib+dirs[n]);
    for (var m in sdirs) {
      if (sdirs[m].indexOf("lib") == 0) {
        //console.log(lib+dirs[n]+'/'+sdirs[m]);
        folders.push(lib+dirs[n]+'/'+sdirs[m]);
      }
    }
  }
  return folders;
}

function addIncludes(file, callback)
{
  var dirs = getFolders(libPath);
  for (var n in dirs) {
    //console.log('-I "'+dirs[n]+'" ');
    buildcmd += '-I "./'+dirs[n]+'" ';
  }
}


function addLibraryPaths(file, callback)
{
  var dirs = fs.readdirSync(libPath);
  var dirs = getFolders(libPath);
  var pwd= process.cwd();

  for (var n in dirs) {
    //console.log('-L"./'+dirs[n]+'/'+memmodel+'/" ');
    buildcmd += '-L"'+pwd+'/'+dirs[n]+'/'+memmodel+'" ';
  }
}

function addLibraries(file, callback)
{
  var dirs = getFolders(libPath);
  var libs = Array();

  libs.push("m");

  for (var n in dirs) {
    var s = dirs[n];
    var lib = s.substr(s.lastIndexOf("/")).replace("/lib","");
    libs.push(lib);
    //console.log('-l'+lib+' ');
  }

  var libstr = "";
  while (libs.length > 1) {
    for (var n = libs.length-1; n > -1; n--) {
      libstr += " -l"+libs[n];
      //console.log('-l'+libs[n]+' ');
    }
    libs.pop();
  }
  buildcmd += libstr;
}

function addMainArgs(file)
{
  //buildcmd += '-L"workspace/libs/'+memmodel+'" ';
  buildcmd += '-o "';
  buildcmd += file.substr(0,file.lastIndexOf("."));
  buildcmd += '" "';
  buildcmd += file;
  buildcmd += '" ';
}

function buildProgram(file, callback)
{
  if (isWindows) {
    console.log("Replacing all path separators for windows - blech.");
    while (buildcmd.indexOf('/') > -1) {
      buildcmd = buildcmd.replace('/','\\');
    }
  }
  //console.log(buildcmd);
  exec(buildcmd, callback);
}

